#include "mainwindow.h"
#include<QtCharts>
QT_CHARTS_USE_NAMESPACE
#include "ui_mainwindow.h"
#include"platform.h"
#include"showplatform.h"
#include "fstream"
#include "SeqList.h"
#include "OLGraph.h"
#include<QDebug>
#include<QFileDialog>
#include<QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QJsonValue>
#include<QStandardPaths>
#include<QMenu>
#include<QQueue>

#include<QValueAxis>
#include <QBarSet>
#include <QBarSeries>
#include <QBarCategoryAxis>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    init();

    connect(ui->treeWidget,SIGNAL(itemClicked(QTreeWidgetItem*,int)),this,SLOT(multilevelMenuItemClicked(QTreeWidgetItem*,int)));

    //响应右键菜单信号槽
     connect(ui->treeView,&QTreeView::customContextMenuRequested,
            this,&MainWindow::slotMenuPopup);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::init()
{
    tabBarInit();
    treeViewInit();
    tableViewInit();
    showPlatform *p=new showPlatform();
    ui->grid->addWidget(p);

    ui->stackedWidget->widget(0)->layout()->setContentsMargins(0,0,0,0);
    ui->stackedWidget->widget(1)->layout()->setContentsMargins(0,0,0,0);
    ui->stackedWidget->widget(2)->layout()->setContentsMargins(0,0,0,0);
    ui->stackedWidget->widget(3)->layout()->setContentsMargins(0,0,0,0);

    ui->tabWidget->setMovable(true);
    model->list = SeqList(110);
    InitSeqList(model->list);
    initOL(model->g,130);
    creatByFile(model->g);

}

void MainWindow::tabBarInit()
{
    ui->treeWidget->setStyleSheet(QString(""
                                           "QWidget{background-color: rgb(33, 45, 62);}"
                                           "QTreeWidget::item{height: 60;}"
                                           "QTreeWidget{background-color: rgb(33, 45, 62);"
                                           "\nfont: 20px 'Microsoft YaHei';\ncolor: rgb(255, 255, 255);}"
                                           "QTreeView::arrow{background-color:white ;}"
                                           )
                                   );


     //隐藏treeWidget的Header
    ui->treeWidget->setHeaderHidden(true);

    QHeaderView *head = ui->treeWidget->header();
    head->setSectionResizeMode(QHeaderView::ResizeToContents);

    //设置treeWidget Icon大小
    ui->treeWidget->setIconSize(QSize(32,32));

    //隐藏treeWidget水平和垂直滚动条
    ui->treeWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui->treeWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    //设置treeWidget展开和隐藏动画
    ui->treeWidget->setAnimated(true);

    //默认展开所有的treeWidget项
    ui->treeWidget->expandAll();

    //设置多级菜单部件的最大宽度
    //this->setMaximumWidth(350);
}

void MainWindow::treeViewInit()
{
    QTreeView* t = ui->treeView;
    //t->setEditTriggers(QTreeView::NoEditTriggers);			//单元格不能编辑
    t->setSelectionBehavior(QTreeView::SelectRows);			//一次选中整行
    t->setSelectionMode(QTreeView::SingleSelection);        //单选，配合上面的整行就是一次选单行
    t->setAlternatingRowColors(true);                       //每间隔一行颜色不一样，当有qss时该属性无效
    t->setFocusPolicy(Qt::NoFocus);                         //去掉鼠标移到单元格上时的虚线框

    //2，列头相关设置
    t->header()->setHighlightSections(true);                //列头点击时字体变粗，去掉该效果
    t->header()->setDefaultAlignment(Qt::AlignCenter);      //列头文字默认居中对齐
//    t->header()->setDefaultSectionSize(100);                //默认列宽100
    t->header()->setStretchLastSection(true);               //最后一列自适应宽度
    t->header()->setSortIndicator(0,Qt::AscendingOrder);    //按第1列升序排序

    //打开右键菜单属性
    t->setContextMenuPolicy(Qt::CustomContextMenu);



    //设置表头
    model=new TreeModel;
    model->setHorizontalHeaderLabels(QStringList()<<"章节"<<"学习时长"<<"知识难度");
    //设置model
    t->setModel(model);

    t->setColumnWidth(0,300);
    t->setColumnWidth(1,100);
    t->setColumnWidth(2,100);


    //设置展开
    ui->treeView->expandAll();
    ui->splitter->setStretchFactor(2,5);



}

void MainWindow::tableViewInit()
{
    this->tableModel = new QStandardItemModel;   //创建一个标准的条目模型
    this->ui->tableView->setModel(tableModel);   //将tableview设置成model这个标准条目模型的模板, model设置的内容都将显示在tableview上

    this->tableModel->setHorizontalHeaderItem(0, new QStandardItem("知识点") );
    this->tableModel->setHorizontalHeaderItem(1, new QStandardItem("前序知识"));
    this->tableModel->setHorizontalHeaderItem(2, new QStandardItem("后序知识"));

    ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    this->ui->tableView->setColumnWidth(0, 100);    //设置列的宽度
    this->ui->tableView->setColumnWidth(1, 200);
    this->ui->tableView->setColumnWidth(2, 200);
}






void MainWindow::multilevelMenuItemClicked(QTreeWidgetItem *p,int i)//i表示列数
{
    QString menu=p->text(i);
    if(menu=="学习路径")
    {
        ui->stackedWidget->setCurrentIndex(1);


    }
    else if(menu=="工作台")
    {
        ui->stackedWidget->setCurrentIndex(0);
    }
    else if(menu=="知识搜索")
    {
        ui->stackedWidget->setCurrentIndex(2);
    }
    else if(menu=="知识分析")
    {
        ui->stackedWidget->setCurrentIndex(3);
    }


    else if(menu=="新建图谱")
    {
        ui->stackedWidget->setCurrentIndex(0);
        platform *p=new platform();
        platforms.append(p);
        int cur=ui->tabWidget->addTab(p,QString::asprintf("未命名%d",ui->tabWidget->count()));
        ui->tabWidget->setCurrentIndex(cur);
    }
    else if(menu=="保存图谱")
    {
       ui->stackedWidget->setCurrentIndex(0);
       int cur= ui->tabWidget->currentIndex();
       qDebug()<<cur;
       if(cur==-1) return ;
       auto nodes=platforms[cur]->nodes;
       auto edges=platforms[cur]->edges;
       QString fileName= QFileDialog::getSaveFileName(this,"另存为",QString("./untitle.json"),"*.json");
       if(fileName.isEmpty())
           return ;
       else
       {
           QFile file(fileName);
           file.open(QIODevice::WriteOnly);
           QJsonArray n_id,e_id;

           for(int i=0;i<nodes.size();i++)
           {
               QJsonArray node;
               node.append(int(nodes[i]->pos.x()));
               node.append(int(nodes[i]->pos.y()));
               node.append(nodes[i]->name->toPlainText());
               n_id.append(node);
           }
           for(int j=0;j<edges.size();j++)
           {
               QJsonArray edge;
               edge.append(edges[j]->s);
               edge.append(edges[j]->e);
               edge.append(edges[j]->weight->toPlainText());
               e_id.append(edge);

           }
           QJsonArray array;
           array.append(n_id);
           array.append(e_id);
           QJsonDocument jsonDoc;
           jsonDoc.setArray(array);

           file.write(jsonDoc.toJson());

           file.close();

       }

    }
    else if(menu=="打开图谱")
    {

        ui->stackedWidget->setCurrentIndex(0);


        QString filePath= QFileDialog::getOpenFileName(this,"打开",QCoreApplication::applicationFilePath(),"*.json");
        if(filePath.isEmpty())
        {
            return ;
        }
        else
        {
            QFileInfo fileInfo = QFileInfo(filePath);

            QString fileName = fileInfo.baseName();
            qDebug()<<fileName;
            platform *p=new platform();
            //int size=p->size;
            platforms.append(p);
            int cur=ui->tabWidget->addTab(p,fileName);
            ui->tabWidget->setCurrentIndex(cur);


            QFile file(filePath);
            file.open(QIODevice::ReadOnly);
            QTextStream in(&file);

            QByteArray allData = file.readAll();
            file.close();
            QJsonParseError json_error;
            QJsonDocument jsonDoc(QJsonDocument::fromJson(allData, &json_error));


            QJsonArray a = jsonDoc.array();
            QJsonArray nodes=a[0].toArray();
            QJsonArray edges=a[1].toArray();
            for(int i=0;i<nodes.size();i++)
            {
                QJsonArray pos=nodes[i].toArray();
                qreal x=pos[0].toInt();
                qreal y=pos[1].toInt();
                QString name=pos[2].toString();
                Node *node=new Node(QPointF(x,y));

                node->name->setPlainText(name);
                p->scene->addItem(node->name);
                p->nodes.append(node);
                p->scene->addItem(node);
            }
            for(int j=0;j<edges.size();j++)
            {
                QJsonArray pos=edges[j].toArray();
                qreal s=pos[0].toInt();
                qreal e=pos[1].toInt();

                Edge *edge=new Edge(p->nodes[s],p->nodes[e]);
                edge->s=s;
                edge->e=e;

                edge->setLine(QLineF(p->nodes[s]->POS(),p->nodes[e]->POS()));
                p->scene->addItem(edge);

                QString weight =pos[2].toString();

                edge->weight->setPlainText(weight);


                p->scene->addItem(edge->weight);
                p->edges.append(edge);
            }


        }
    }
}



void MainWindow::on_tabWidget_tabCloseRequested(int index)
{

    ui->tabWidget->removeTab(index);
    platform *p=platforms[index];
    delete p;
    platforms[index]=NULL;

}

void MainWindow::on_search_but_clicked()
{

    QString mes=ui->lineEdit->text();
    //接下来是调用搜索算法输出一个字符串
    string s = mes.toStdString();
    while(s.back() == ' ') s.pop_back();
    if(s=="") return ;
    tableModel->clear();
    tableViewInit();
    SeqList* res = SLmatch(model->list,s);
    qDebug()<<res;
    for(int i = 0;i < res->length;i ++){
        int index = locateVertex(model->g,res->elem[i].name);
        arcBox* arc = model->g.xList[index].firstIn;

        QString s0=QString::fromStdString(res->elem[i].name);

        //QString ans="搜索结果："+QString::fromStdString(res->elem[i].name)+"\n"+"前序知识:";
        QString s1="";
        while (arc) {
            s1 = s1 + QString::fromStdString(model->g.xList[arc->tailVex].data)+" ";
            arc = arc->hLink;
        }

        arc = model->g.xList[index].firstOut;
        //ans = ans + "\n"+"后续知识:";
        QString s2="";
        while (arc) {
            s2 = s2 + QString::fromStdString(model->g.xList[arc->headVex].data) + " ";
            arc = arc->tLink;
        }

        QStandardItem *itemColumn1 = new QStandardItem(s0);
        QStandardItem *itemColumn2 = new QStandardItem(s1);
        QStandardItem *itemColumn3 = new QStandardItem(s2);
        QList<QStandardItem*> list = QList<QStandardItem*>();
        list.append(itemColumn1);
        list.append(itemColumn2);
        list.append(itemColumn3);
        tableModel->appendRow(list);


        //ans = ans + "\n";
//        ui->search_ans->insertPlainText(ans);
//        ui->search_ans->insertPlainText("\n");
    }
}

void MainWindow::slotMenuPopup(const QPoint &pos)
{
    qDebug()<<pos;
    QString qss = "QMenu{color:#E8E8E8;background:#4D4D4D;margin:2px;}\
                    QMenu::item{padding:3px 20px 3px 20px;}\
                    QMenu::indicator{width:13px;height:13px;}\
                    QMenu::item:selected{color:#E8E8E8;border:0px solid #575757;background:#1E90FF;}\
                    QMenu::separator{height:1px;background:#757575;}";

        menu=new QMenu;
        menu->setStyleSheet(qss);    //可以给菜单设置样式

        QModelIndex curIndex = ui->treeView->indexAt(pos);      //当前点击的元素的index
        QModelIndex index = curIndex.sibling(curIndex.row(),0); //该行的第1列元素的index
        if (index.isValid())
        {
            //可获取元素的文本、data,进行其他判断处理
            //QStandardItem* item = mModel->itemFromIndex(index);
            //QString text = item->text();
            //QVariant data = item->data(Qt::UserRole + 1);
            //...

            //添加一行菜单，进行展开
            menu->addAction(QStringLiteral("添加行"), this, [=](){
                QStandardItem* item = model->itemFromIndex(index);
                int index = locateVertex(model->g,item->text().toStdString());
                arcBox* arc = model->g.xList[index].firstIn;
                insertNode(model->g,"#");
                insertArc(model->g,model->g.xList[arc->tailVex].data,"#");
                KLmeta meta = {"#",1,1};
                SeqListPush_back(model->list,meta);
                QStandardItem *itemColumn0 = new QStandardItem("#");
                QStandardItem *itemColumn1 = new QStandardItem("");
                QStandardItem *itemColumn2 = new QStandardItem("");
                QList<QStandardItem*> list = QList<QStandardItem*>();
                list.append(itemColumn0);
                list.append(itemColumn1);
                list.append(itemColumn2);

                int r=item->row();

                if(item->parent()!=NULL)
                {
                    item->parent()->insertRow(r+1,list);
                }
                else
                {
                    model->insertRow(r+1,list);
                }
            }
            );
            menu->addSeparator();    //添加一个分隔线

            menu->addAction(QStringLiteral("添加子项"), this, [=](){
                QStandardItem* item = model->itemFromIndex(index);
                insertNode(model->g,"#");
                insertArc(model->g,item->text().toStdString(),"#");
                KLmeta meta = {"#",1,1};
                SeqListPush_back(model->list,meta);
                QStandardItem *itemColumn1 = new QStandardItem("#");
                QStandardItem *itemColumn2 = new QStandardItem("1");
                QStandardItem *itemColumn3 = new QStandardItem("1");
                QList<QStandardItem*> list = QList<QStandardItem*>();
                list.append(itemColumn1);
                list.append(itemColumn2);
                list.append(itemColumn3);
                item->appendRow(list);

            }

            );
            menu->addSeparator();    //添加一个分隔线
            menu->addAction(QStringLiteral("删除"), this, [=](){
                QStandardItem* item = model->itemFromIndex(index);
                qDebug() << item->text();
                string data = item->text().toStdString();
                deleteNode(model->g,data);
                SeqListDelete(model->list,SLsearch(model->list,data)+1);
                int r=item->row();
                if(item->parent()!=NULL)
                {
                    item->parent()->removeRow(r);
                }
                else
                {
                    model->removeRow(r);
                }
            });
        }
        menu->exec(QCursor::pos());  //显示菜单


}

void MainWindow::on_drive_but_clicked()
{
    for(int i = 0;i < model->list.length;i ++){
        qDebug() << QString::fromStdString(model->list.elem[i].name);
        qDebug() << model->list.elem[i].hours;
        qDebug() << model->list.elem[i].difficulty;
    }
    OutPutSL(model->list);
    OutPutOL(model->g);
}

void MainWindow::setItem(int index,QStandardItem* item){
    arcBox* arc = model->g.xList[index].firstOut;
    while(arc){
        int index = SLsearch(model->list,model->g.xList[arc->headVex].data);
        if(index == -1) {arc = arc -> tLink;continue;}
        KLmeta t = model->list.elem[index];
        QStandardItem *it = new QStandardItem(QString::fromStdString(t.name));
        if(model->g.xList[arc->headVex].firstOut) {
            setItem(arc->headVex,it);
            item->appendRow(it);
        }
        else{
            QList<QStandardItem*> lt = QList<QStandardItem*>();
            QStandardItem *it1 = new QStandardItem(QString::number(t.difficulty));
            QStandardItem *it2 = new QStandardItem(QString::number(t.hours));
            lt.append(it);
            lt.append(it2);
            lt.append(it1);
            item->appendRow(lt);
        }
        arc = arc -> tLink;
    }
}

void MainWindow::on_load_but_clicked()
{
    int index = locateVertex(model->g,"数据结构与算法");
    arcBox* arc = model->g.xList[index].firstOut;
    int cnt = 0;
    while(arc){
        KLmeta t = model->list.elem[SLsearch(model->list,model->g.xList[arc->headVex].data)];
        QStandardItem *item = new QStandardItem(QString::fromStdString(t.name));
        setItem(arc->headVex,item);
        arc = arc -> tLink;
        model -> setItem(cnt++,0,item);
    }

    GetNode();
    drawBarLine();

}
//增加双击修改结点功能，会对应修改数据结构中的数据
void MainWindow::on_treeView_doubleClicked(const QModelIndex &index)
{
    qDebug() << "修改";
    QStandardItem* item = model->itemFromIndex(index);
    qDebug() << item->text();
}

void MainWindow::drawBarLine()
{

    QBarSeries *barseries = new QBarSeries();
    QBarSet *set0 = new QBarSet("时长");

    QLineSeries *lineseries=new QLineSeries();
    lineseries->setName("难度");
    QList<QPointF> lsPnt;


    qsrand(QTime::currentTime().second());
    for(int i=0;i<data.size();i++)
    {
        set0->append(data[i]->hour);
        lsPnt.append(QPointF(i,data[i]->dif));
    }


    barseries->append(set0);
    lineseries->replace(lsPnt);

    QPen pen;
    pen.setStyle(Qt::DotLine);
    pen.setWidth(4);
    pen.setColor(Qt::red);
    lineseries->setPen(pen);


    QScatterSeries *series1 = new QScatterSeries();
    series1->setMarkerShape(QScatterSeries::MarkerShapeCircle);//圆形的点
    series1->setBorderColor(QColor(21, 100, 255)); //离散点边框颜色
    series1->setBrush(QBrush(QColor(21, 100, 255)));//离散点背景色
    series1->setMarkerSize(12); //离散点大小
    series1->replace(lsPnt);



    QChart *chart=new QChart();
    chart->addSeries(barseries);//难度
    chart->addSeries(lineseries);//时长
    chart->addSeries(series1);//时长
    chart->setTitle("知识点分析");
    chart->setAnimationOptions(QChart::SeriesAnimations);



    QStringList categories;


    for(int i=0;i<data.size();i++)
    {
        //qDebug()<<data[i]->name;
        categories.append(data[i]->name);
    }


    QBarCategoryAxis *axisX = new QBarCategoryAxis();
    axisX->append(categories);
    chart->setAxisX(axisX,barseries);
    chart->setAxisX(axisX,lineseries);
    chart->setAxisX(axisX,series1);
    axisX->setRange(categories[0],categories[6]);//设置可见0-4

    QValueAxis *axisY=new QValueAxis();
    chart->setAxisY(axisY,barseries);
    chart->setAxisY(axisY,lineseries);
    chart->setAxisY(axisY,series1);
    axisY->setRange(0,10);



    //chart->createDefaultAxes();



    chart->legend()->setVisible(true);
    chart->legend()->setAlignment(Qt::AlignTop);//设置图例的显示位置在顶部
    chart->legend()->markers().last()->setVisible(false);
    ui->chartView->setChart(chart);
    ui->chartView->setRenderHint(QPainter::Antialiasing);//抗锯齿
    ui->horizontalScrollBar->setRange(0, data.size()/3-1);  //设置QScrollBar的滚动范围
    ui->horizontalScrollBar->setPageStep(1); //设置步长

}




void MainWindow::on_horizontalScrollBar_valueChanged(int value)
{
    auto xlength=ui->chartView->chart()->plotArea().width();

    if(curRange<value)
    {
        ui->chartView->chart()->scroll(xlength,0);
    }
    else
    {
        ui->chartView->chart()->scroll(-xlength,0);
    }
    curRange=value;
}


void MainWindow::GetNode()
{
    data.clear();
    for(int i = 0;i < model->rowCount() ;i++)
    {
            GetItem(model->item(i));
    }
}

void MainWindow::GetItem(QStandardItem *item)
{
    if(item->hasChildren())
    {
        for(int i = 0;i < item->rowCount() ;i++)
        {
            QStandardItem * childitem = item->child(i);
            GetItem(childitem);
        }
    }
    else
    {
        QModelIndex index=item->index();
        QModelIndex index_1 = index.sibling(index.row(),1);
        QModelIndex index_2 = index.sibling(index.row(),2);
        QStandardItem* item_1 = model->itemFromIndex(index_1);
        QStandardItem* item_2 = model->itemFromIndex(index_2);
        QString n=item->text();
        int h=item_1->text().toInt();
        int d=item_2->text().toInt();
        knowledge *k=new knowledge(n,h,d);
        data.append(k);
    }
}

void MainWindow::updateChart()
{
    ui->chartView->chart()->removeAllSeries();
    GetNode();
    drawBarLine();

}

#define MIDDLE(a, b, c) max(min((a), (b)), min(max((a), (b)), (c))) //求中间值


void MainWindow::InsertSort_hour(int m, int n)   //插入排序
{
    int i, j;
    int temp; // 用来存放临时的变量
    for(i = m+1; i <= n; i++)
    {
        temp = data[i]->hour;
        for(j = i-1; (j >= m)&&(data[j]->hour > temp); j--)
        {
            data[j + 1]=data[j];
        }
        data[j + 1]->hour = temp;
    }
}

void MainWindow::InsertSort_diff(int m, int n)   //插入排序
{
    int i, j;
    int temp; // 用来存放临时的变量
    for(i = m+1; i <= n; i++)
    {
        temp = data[i]->dif;
        for(j = i-1; (j >= m)&&(data[j]->dif > temp); j--)
        {
            data[j + 1]=data[j];
        }
        data[j + 1]->dif = temp;
    }
}

void MainWindow::quick_sort_hour(int l,int r){
    while(l >= r) return;
    int mid = MIDDLE(data[l]->hour,data[r]->hour,data[l+r >> 1]->hour);  //三数取中
    int i = l - 1, j = r + 1;
    while(i < j){
        do i ++;while(data[i]->hour < mid);
        do j --;while(data[j]->hour > mid);
        if(i < j) swap(data[j],data[i]);
    }
    quick_sort_hour(l,j);
    quick_sort_hour(j+1,r);
}

void MainWindow::quick_sort_diff(int l,int r){
    while(l >= r) return;
    int mid = MIDDLE(data[l]->dif,data[r]->dif,data[l+r >> 1]->dif);  //三数取中
    int i = l - 1, j = r + 1;
    while(i < j){
        do i ++;while(data[i]->dif < mid);
        do j --;while(data[j]->dif > mid);
        if(i < j) swap(data[j],data[i]);
    }
    quick_sort_diff(l,j);
    quick_sort_diff(j+1,r);
}
void MainWindow::on_hour_order_but_clicked()
{
    ui->chartView->chart()->removeAllSeries();
    GetNode();

    quick_sort_hour(0,data.size()-1);

    drawBarLine();
}

void MainWindow::on_dif_order_but_clicked()
{
    ui->chartView->chart()->removeAllSeries();
    GetNode();

    quick_sort_diff(0,data.size()-1);

    drawBarLine();
}
